package core;

import java.io.*;
import java.net.*;
import java.util.logging.Logger;

import util.*;

public class NetClient {
	private static Logger log = Logger.getLogger(NetClient.class.getName());
	public static volatile int clientSequenceId;
	public static volatile int clientReferenceId;
	private Client client;
	private Socket requestSocket;
	private ObjectOutputStream out;
	private ObjectInputStream in;
	private NetworkReader netReader;

	public NetClient(Client client) {
		this.client = client;
		netReader = new NetworkReader(this);
	}
	
	public boolean connect(String host, int port) {
		try {
			requestSocket = new Socket(host, port);
			out = new ObjectOutputStream(requestSocket.getOutputStream());
			in  = new ObjectInputStream(requestSocket.getInputStream());
			return true;
			
		} catch (IOException e) {
			log.warning("server is not available");
			return false;
		}
	}
	
	public void start() {
		new Thread(new Runnable() {
			@Override
			public void run() {
				while(!Thread.interrupted()){
					receiveMessage();
				}
			}		
		}).start();
	}
	
	public String receiveMessage() {
		try {
			final String msg = (String)in.readObject();
			netReader.update(msg);
			log.info(msg);
			return msg;
		} catch (ClassNotFoundException | IOException e) {
			log.warning("server is not available, disconnecting.");
			Thread.currentThread().interrupt();
			disconnect();
		} catch(NullPointerException e) {
			log.warning("NullPointerException");
			Thread.currentThread().interrupt();
		}
		return null;
	}
	
	public void sendMessage(String msg) {
		try {
			out.writeObject(msg);
			out.flush();
			log.info(msg);				
		} catch (IOException e) {
			log.warning("server is not available, disconnecting.");
			disconnect();
			Thread.currentThread().interrupt();
		} catch (NullPointerException e) {
			log.warning("NullPointerException");
			disconnect();
			Thread.currentThread().interrupt();
		}
	}

	public void disconnect() {
		try {
			in.close();
		} catch (IOException e) {
			log.warning("INPUT cannot be closed");
			Thread.currentThread().interrupt();
		}
		try {
			out.close();
		} catch (IOException e) {
			log.warning("OUTPUT cannot be closed");
			Thread.currentThread().interrupt();
		}
		try {
			requestSocket.close();
		} catch (IOException e) {
			log.warning("SOCKET cannot be closed");
			Thread.currentThread().interrupt();
		}
	}
	
	public Client getClient() {
		return this.client;
	}
	
	public NetworkReader getGuiChanger() {
		return netReader;
	}
	
}
